Advanced Data Journalism Final Project
Data from: https://ephtracking.cdc.gov/DataExplorer/?c=35&i=88&m=-1
https://ephtracking.cdc.gov/DataExplorer/?c=35&i=88&m=-1
https://public.tableau.com/app/profile/samantha2462/viz/shared/437ZHKXJZ
https://moboscoc.org/resources/data/point-in-time-count-reports/
Step 1: Load libraries
library(plotly)
Registered S3 method overwritten by 'data.table':
method from
print.data.table
Attaching package: ‘plotly’
The following object is masked from ‘package:ggplot2’:
last_plot
The following object is masked from ‘package:stats’:
filter
The following object is masked from ‘package:graphics’:
layout
Step 2: Load data
We will be using three data sets. One contains the coordinates and
details for cooling centers serving Missouri and the other contains
heat-related hospitalizations over the last several years. I also loaded
population data from the Census.
coolingcenters <- read_csv("Final Project/Missouri_Cooling_Centers_Sites.csv")
heathospitalizations <- read_csv("Final Project/heatrate.csv")
hud_mo <- read_csv("Final Project/HUDmo.csv")
Step 3: Clean data
Clean & organize cooling centers data.
Our data needs to be properly — and specifically — formatted so it
can be easily visualized.
#First, I'm separating the latitude and longitude into separate boxes.
coolingcentersclean <- coolingcenters %>%
separate(Location, sep=", ", into=c("latitude", "longitude"))
#I'm also cleaning up these boxes by removing the parentheses from them.
coolingcentersclean <- coolingcentersclean %>%
mutate(lat = str_replace(latitude, "[(]", ""))
coolingcentersclean <- coolingcentersclean %>%
mutate(long = str_replace(longitude, "[)]", ""))
#I'm going to change the state abbreviations to their names so it will be easier to combine with the states data.
coolingcentersclean <- coolingcentersclean %>% mutate(region = case_when(
grepl("MO", state, ignore.case=T) ~ "missouri",
grepl("IL", state, ignore.case=T) ~ "illinois",
grepl("KS", state, ignore.case=T) ~ "kansas"))
#I'm going to remove the improperly formatting latitude and longitude from the dataset.
coolingcentersclean <- subset (coolingcentersclean, select = -latitude)
coolingcentersclean <- subset (coolingcentersclean, select = -longitude)
#We'll need our coordinates to be numbers so we can plot them.
coolingcentersclean$lat <- as.numeric(coolingcentersclean$lat)
coolingcentersclean$long <- as.numeric(coolingcentersclean$long)
#Lastly, I'll be cleaning the names with janitor.
coolingcentersclean <- clean_names(coolingcentersclean)
Clean & organize heat data
#This dataset is relatively clean, so I'm just going to clean the names and then remove the column at the end.
heathospitalizations <- clean_names(heathospitalizations)
heathosptializations <- tolower(heathospitalizations$state)
heathospitalizations <- subset (heathospitalizations, select = -x6)
Clean & organize county pop data
county_pop <- clean_names(county_pop)
county_pop <- county_pop %>% separate(name, sep=",", into=c("county", "state"))
county_pop <- county_pop %>% mutate(county = str_replace(county, " County", ""))
Clean & organize projected heat data
projectedheat <- clean_names(projectedheat)
Clean & organize HUD data
Step 4: Load map data
states <- map_data("state") %>% filter(region=="missouri" | region == "illinois" | region == "kansas")
statescounties <- map_data("county") %>% filter(region == "missouri" | region == "illinois" | region == "kansas")
mocounties <- map_data("county") %>% filter(region == "missouri")
countiesall <- map_data("county")
Step 5: Create custom interactive dot map
By using county-level data from the maps package and plotly, we can
create our own custom interactive dot map.
staticdotmap_ <- ggplot(statescounties, aes(x = long, y = lat, group = group)) +
geom_polygon(fill = "#F8F9F9", color = "darkgray", linewidth=.1) +
geom_point(data=coolingcentersclean, aes(group = NULL, text = paste("Location:", facility)), alpha=.5, size=.7, color="#EE9253") +
coord_fixed(1.3) +
theme_void() +
labs(title="Cooling Centers in Missouri", caption = "Data from data.mo.gov") + theme_void()
staticdotmap <- ggplotly(staticdotmap_, tooltip = "text")
Step 6: Create interactive dot map with leaflet
Leaflet is a simpler way to plot data interactively.
interactivedotmap <- leaflet() %>%
addProviderTiles(providers$CartoDB.Positron) %>%
addCircleMarkers(
data = coolingcentersclean,
color = "#EE9253",
opacity = 0.5,
radius = 1,
~long, ~lat, popup = ~htmlEscape(facility))
Step 8: Create an interactive bar graph
Similar to how we created a custom interactive dot map, we can do the
same for bar graphs.
#I'm going to create a tooltip first to make the bar graph interactive.
heathospitalizations <- heathospitalizations %>% mutate(
tooltip_text = paste0(year, " - ", value, "%"))
#Now, I'm going to use ggplot to create the bar graph.
bar_graph_ <- heathospitalizations %>%
filter(state=="Missouri") %>%
ggplot(aes(x=year, y=value, tooltip = tooltip_text, data_id = state)) +
geom_col_interactive(width=.7, fill="#EE9253", size = 0.2) +
theme_minimal() +
theme(axis.text=element_text(size = 7), axis.title=element_text(size=7), title=element_text(size=7)) +
labs(title = "Percentage of heat-related illness hospitalizations in Missouri per 100k people",subtitle = "Data from CDC") +
ylab("Percentage of heat hospitalizations") +
xlab("Year") +
geom_hline(yintercept = 2.010133,color="red", linewidth=.5)
#Girafe will let us make the graph interactive.
bar_graph <- girafe(ggobj = bar_graph_, width_svg = 5, height_svg = 3)
chloro_map <- girafe(ggobj = chloro_map, width_svg = 5, height_svg = 3)
Error:
! `ggobj` must be a ggplot2 plot
Backtrace:
1. ggiraph::girafe(ggobj = chloro_map, width_svg = 5, height_svg = 3)
Step 9: Some basic analysis
coolingcentersclean %>%
filter(transportation == "Yes")
#No centers provide transportation
coolingcentersclean %>%
filter(ada_accessible == "No")
#All centers are ADA accessible
coolingcentersclean %>%
group_by(county) %>%
count(county) %>%
arrange(desc(n))
#Jackson County has the most cooling centers followed by St. Louis county and then Madison
coolingcentersclean %>%
filter(county == "Boone")
#Boone County has 6 cooling centers
coolingcentersclean %>%
filter(grepl("sun", hours_of_operation, ignore.case=T))
#58 centers are open on Sundays
heathospitalizations %>%
arrange(desc(value))
#California had the highest heat-related hospitalization rate in 2020; Missouri had the sixth highest rate in 2011 at 7.6.
heathospitalizations %>%
filter(state=="Missouri") %>%
arrange(desc(value))
#Missouri had its highest number of heat-related hospitalizations in 2011
heathospitalizations %>%
summarise(average = mean(value))
#The average percentage of heat-related illness hospitalizations from 2000 to 2021 using availble data was 2.010133%.
heathospitalizations %>%
group_by(state) %>%
summarise(average = mean(value)) %>%
arrange(desc(average))
#Missouri has the second highest rate of the data reported.
projectedheat %>%
group_by(state) %>%
summarise(average=mean(value)) %>%
arrange(desc(average))
#Missouri ranks tenth in "projected difference in extreme heat days as compared to the historical period" with an average across the state of about 24 days.
Story Package
Important statistics and data analysis to include in the
story:
In the last two decades, Missouri ranks in the top ten out of
reporting states for the highest rate of heat-related illnesses per
100,000 people. In 2011, the rate in Missouri reached 7.6%, ranking it
number 6 behind Arizona.
Missouri currently reports 538 cooling centers. 58 of those cooling
centers are open on Sundays.
Graphs to include in the story:

animatedgraph
bar_graph +
transition_states(year,
transition_length = 2,
state_length = 1) +
ease_aes('sine-in-out')
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyAqKkFkdmFuY2VkIERhdGEgSm91cm5hbGlzbSBGaW5hbCBQcm9qZWN0KioKCkRhdGEgZnJvbTogPGh0dHBzOi8vZXBodHJhY2tpbmcuY2RjLmdvdi9EYXRhRXhwbG9yZXIvP2M9MzUmaT04OCZtPS0xPgoKPGh0dHBzOi8vZXBodHJhY2tpbmcuY2RjLmdvdi9EYXRhRXhwbG9yZXIvP2M9MzUmaT04OCZtPS0xPgoKPGh0dHBzOi8vcHVibGljLnRhYmxlYXUuY29tL2FwcC9wcm9maWxlL3NhbWFudGhhMjQ2Mi92aXovc2hhcmVkLzQzN1pIS1hKWj4KCmh0dHBzOi8vbW9ib3Njb2Mub3JnL3Jlc291cmNlcy9kYXRhL3BvaW50LWluLXRpbWUtY291bnQtcmVwb3J0cy8KCgojIyMgU3RlcCAxOiBMb2FkIGxpYnJhcmllcwoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGx1YnJpZGF0ZSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGphbml0b3IpCmxpYnJhcnkobWFwcykKbGlicmFyeShzZikKbGlicmFyeShsZWFmbGV0KQpsaWJyYXJ5KHNwRGF0YSkKbGlicmFyeSh0aWR5Y2Vuc3VzKQpsaWJyYXJ5KGdnaXJhcGgpCmxpYnJhcnkocGxvdGx5KQoKI0FuaW1hdGlvbiBMaWJyYXJpZXMKbGlicmFyeShnZ2FuaW1hdGUpCmxpYnJhcnkoc3ApCmxpYnJhcnkodmlyaWRpcykKbGlicmFyeShodG1sdG9vbHMpCmxpYnJhcnkoZ2FwbWluZGVyKQpsaWJyYXJ5KGdpZnNraSkKbGlicmFyeShwbmcpCmxpYnJhcnkodG1hcCkKCgpgYGAKCiMjIyBTdGVwIDI6IExvYWQgZGF0YQoKV2Ugd2lsbCBiZSB1c2luZyB0aHJlZSBkYXRhIHNldHMuIE9uZSBjb250YWlucyB0aGUgY29vcmRpbmF0ZXMgYW5kIGRldGFpbHMgZm9yIGNvb2xpbmcgY2VudGVycyBzZXJ2aW5nIE1pc3NvdXJpIGFuZCB0aGUgb3RoZXIgY29udGFpbnMgaGVhdC1yZWxhdGVkIGhvc3BpdGFsaXphdGlvbnMgb3ZlciB0aGUgbGFzdCBzZXZlcmFsIHllYXJzLiBJIGFsc28gbG9hZGVkIHBvcHVsYXRpb24gZGF0YSBmcm9tIHRoZSBDZW5zdXMuCgpgYGB7cn0KY29vbGluZ2NlbnRlcnMgPC0gcmVhZF9jc3YoIkZpbmFsIFByb2plY3QvTWlzc291cmlfQ29vbGluZ19DZW50ZXJzX1NpdGVzLmNzdiIpCgpoZWF0aG9zcGl0YWxpemF0aW9ucyA8LSByZWFkX2NzdigiRmluYWwgUHJvamVjdC9oZWF0cmF0ZS5jc3YiKQoKaHVkX21vIDwtIHJlYWRfY3N2KCJGaW5hbCBQcm9qZWN0L0hVRG1vLmNzdiIpCmBgYAoKIyMjIFN0ZXAgMzogQ2xlYW4gZGF0YQoKQ2xlYW4gJiBvcmdhbml6ZSBjb29saW5nIGNlbnRlcnMgZGF0YS4KCk91ciBkYXRhIG5lZWRzIHRvIGJlIHByb3Blcmx5IC0tLSBhbmQgc3BlY2lmaWNhbGx5IC0tLSBmb3JtYXR0ZWQgc28gaXQgY2FuIGJlIGVhc2lseSB2aXN1YWxpemVkLgoKYGBge3J9CiNGaXJzdCwgSSdtIHNlcGFyYXRpbmcgdGhlIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgaW50byBzZXBhcmF0ZSBib3hlcy4gCmNvb2xpbmdjZW50ZXJzY2xlYW4gPC0gY29vbGluZ2NlbnRlcnMgJT4lIAogIHNlcGFyYXRlKExvY2F0aW9uLCBzZXA9IiwgIiwgaW50bz1jKCJsYXRpdHVkZSIsICJsb25naXR1ZGUiKSkKCiNJJ20gYWxzbyBjbGVhbmluZyB1cCB0aGVzZSBib3hlcyBieSByZW1vdmluZyB0aGUgcGFyZW50aGVzZXMgZnJvbSB0aGVtLgpjb29saW5nY2VudGVyc2NsZWFuIDwtIGNvb2xpbmdjZW50ZXJzY2xlYW4gJT4lCiBtdXRhdGUobGF0ID0gc3RyX3JlcGxhY2UobGF0aXR1ZGUsICJbKF0iLCAiIikpCgpjb29saW5nY2VudGVyc2NsZWFuIDwtIGNvb2xpbmdjZW50ZXJzY2xlYW4gJT4lCiBtdXRhdGUobG9uZyA9IHN0cl9yZXBsYWNlKGxvbmdpdHVkZSwgIlspXSIsICIiKSkKCiNJJ20gZ29pbmcgdG8gY2hhbmdlIHRoZSBzdGF0ZSBhYmJyZXZpYXRpb25zIHRvIHRoZWlyIG5hbWVzIHNvIGl0IHdpbGwgYmUgZWFzaWVyIHRvIGNvbWJpbmUgd2l0aCB0aGUgc3RhdGVzIGRhdGEuCmNvb2xpbmdjZW50ZXJzY2xlYW4gPC0gY29vbGluZ2NlbnRlcnNjbGVhbiAlPiUgbXV0YXRlKHJlZ2lvbiA9IGNhc2Vfd2hlbigKICBncmVwbCgiTU8iLCBzdGF0ZSwgaWdub3JlLmNhc2U9VCkgfiAibWlzc291cmkiLAogIGdyZXBsKCJJTCIsIHN0YXRlLCBpZ25vcmUuY2FzZT1UKSB+ICJpbGxpbm9pcyIsCiAgZ3JlcGwoIktTIiwgc3RhdGUsIGlnbm9yZS5jYXNlPVQpIH4gImthbnNhcyIpKQoKI0knbSBnb2luZyB0byByZW1vdmUgdGhlIGltcHJvcGVybHkgZm9ybWF0dGluZyBsYXRpdHVkZSBhbmQgbG9uZ2l0dWRlIGZyb20gdGhlIGRhdGFzZXQuIApjb29saW5nY2VudGVyc2NsZWFuIDwtIHN1YnNldCAoY29vbGluZ2NlbnRlcnNjbGVhbiwgc2VsZWN0ID0gLWxhdGl0dWRlKQpjb29saW5nY2VudGVyc2NsZWFuIDwtIHN1YnNldCAoY29vbGluZ2NlbnRlcnNjbGVhbiwgc2VsZWN0ID0gLWxvbmdpdHVkZSkKCiNXZSdsbCBuZWVkIG91ciBjb29yZGluYXRlcyB0byBiZSBudW1iZXJzIHNvIHdlIGNhbiBwbG90IHRoZW0uCmNvb2xpbmdjZW50ZXJzY2xlYW4kbGF0IDwtIGFzLm51bWVyaWMoY29vbGluZ2NlbnRlcnNjbGVhbiRsYXQpCmNvb2xpbmdjZW50ZXJzY2xlYW4kbG9uZyA8LSBhcy5udW1lcmljKGNvb2xpbmdjZW50ZXJzY2xlYW4kbG9uZykKCiNMYXN0bHksIEknbGwgYmUgY2xlYW5pbmcgdGhlIG5hbWVzIHdpdGggamFuaXRvci4gCmNvb2xpbmdjZW50ZXJzY2xlYW4gPC0gY2xlYW5fbmFtZXMoY29vbGluZ2NlbnRlcnNjbGVhbikKYGBgCgpDbGVhbiAmIG9yZ2FuaXplIGhlYXQgZGF0YQoKYGBge3J9CiNUaGlzIGRhdGFzZXQgaXMgcmVsYXRpdmVseSBjbGVhbiwgc28gSSdtIGp1c3QgZ29pbmcgdG8gY2xlYW4gdGhlIG5hbWVzIGFuZCB0aGVuIHJlbW92ZSB0aGUgY29sdW1uIGF0IHRoZSBlbmQuCmhlYXRob3NwaXRhbGl6YXRpb25zIDwtIGNsZWFuX25hbWVzKGhlYXRob3NwaXRhbGl6YXRpb25zKQpoZWF0aG9zcHRpYWxpemF0aW9ucyA8LSB0b2xvd2VyKGhlYXRob3NwaXRhbGl6YXRpb25zJHN0YXRlKQoKaGVhdGhvc3BpdGFsaXphdGlvbnMgPC0gc3Vic2V0IChoZWF0aG9zcGl0YWxpemF0aW9ucywgc2VsZWN0ID0gLXg2KQpgYGAKCkNsZWFuICYgb3JnYW5pemUgY291bnR5IHBvcCBkYXRhCgpgYGB7cn0KY291bnR5X3BvcCAgPC0gY2xlYW5fbmFtZXMoY291bnR5X3BvcCkKY291bnR5X3BvcCA8LSBjb3VudHlfcG9wICU+JSBzZXBhcmF0ZShuYW1lLCBzZXA9IiwiLCBpbnRvPWMoImNvdW50eSIsICJzdGF0ZSIpKQpjb3VudHlfcG9wIDwtIGNvdW50eV9wb3AgJT4lICBtdXRhdGUoY291bnR5ID0gc3RyX3JlcGxhY2UoY291bnR5LCAiIENvdW50eSIsICIiKSkKYGBgCgpDbGVhbiAmIG9yZ2FuaXplIHByb2plY3RlZCBoZWF0IGRhdGEKCmBgYHtyfQpwcm9qZWN0ZWRoZWF0IDwtIGNsZWFuX25hbWVzKHByb2plY3RlZGhlYXQpCmBgYAoKQ2xlYW4gJiBvcmdhbml6ZSBIVUQgZGF0YQpgYGB7cn0KaHVkX21vIDwtIGNsZWFuX25hbWVzKGh1ZF9tbykKaHVkX21vIDwtIGh1ZF9tbyAlPiUgcmVuYW1lKHVuc2hlbHRlcmVkX3RvdGFsID0gbWVhc3VyZV92YWx1ZXMpCmBgYAoKIyMjIFN0ZXAgNDogTG9hZCBtYXAgZGF0YQoKYGBge3J9CnN0YXRlcyA8LSBtYXBfZGF0YSgic3RhdGUiKSAlPiUgZmlsdGVyKHJlZ2lvbj09Im1pc3NvdXJpIiB8IHJlZ2lvbiA9PSAiaWxsaW5vaXMiIHwgcmVnaW9uID09ICJrYW5zYXMiKQoKc3RhdGVzY291bnRpZXMgPC0gbWFwX2RhdGEoImNvdW50eSIpCgptb2NvdW50aWVzIDwtIG1hcF9kYXRhKCJjb3VudHkiKSAlPiUgZmlsdGVyKHJlZ2lvbiA9PSAgIm1pc3NvdXJpIikKCmNvdW50aWVzYWxsIDwtIG1hcF9kYXRhKCJjb3VudHkiKQpgYGAKCiMjIyBTdGVwIDU6IENyZWF0ZSBjdXN0b20gaW50ZXJhY3RpdmUgZG90IG1hcApCeSB1c2luZyBjb3VudHktbGV2ZWwgZGF0YSBmcm9tIHRoZSBtYXBzIHBhY2thZ2UgYW5kIHBsb3RseSwgd2UgY2FuIGNyZWF0ZSBvdXIgb3duIGN1c3RvbSBpbnRlcmFjdGl2ZSBkb3QgbWFwLgoKYGBge3J9CnN0YXRpY2RvdG1hcF8gPC0gZ2dwbG90KHN0YXRlc2NvdW50aWVzLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApKSArCiAgZ2VvbV9wb2x5Z29uKGZpbGwgPSAiI0Y4RjlGOSIsIGNvbG9yID0gImRhcmtncmF5IiwgbGluZXdpZHRoPS4xKSArCiAgZ2VvbV9wb2ludChkYXRhPWNvb2xpbmdjZW50ZXJzY2xlYW4sIGFlcyhncm91cCA9IE5VTEwsIHRleHQgPSBwYXN0ZSgiTG9jYXRpb246IiwgZmFjaWxpdHkpKSwgICBhbHBoYT0uNSwgc2l6ZT0uNywgY29sb3I9IiNFRTkyNTMiKSArICAgCiAgY29vcmRfZml4ZWQoMS4zKSArCiAgdGhlbWVfdm9pZCgpICsKICBsYWJzKHRpdGxlPSJDb29saW5nIENlbnRlcnMgaW4gTWlzc291cmkiLCBjYXB0aW9uID0gIkRhdGEgZnJvbSBkYXRhLm1vLmdvdiIpICsgdGhlbWVfdm9pZCgpCgpzdGF0aWNkb3RtYXAgPC0gZ2dwbG90bHkoc3RhdGljZG90bWFwXywgdG9vbHRpcCA9ICJ0ZXh0IikKYGBgCgojIyMgU3RlcCA2OiBDcmVhdGUgaW50ZXJhY3RpdmUgZG90IG1hcCB3aXRoIGxlYWZsZXQKTGVhZmxldCBpcyBhIHNpbXBsZXIgd2F5IHRvIHBsb3QgZGF0YSBpbnRlcmFjdGl2ZWx5LiAKCmBgYHtyfQppbnRlcmFjdGl2ZWRvdG1hcCA8LSBsZWFmbGV0KCkgJT4lIAogICAgYWRkUHJvdmlkZXJUaWxlcyhwcm92aWRlcnMkQ2FydG9EQi5Qb3NpdHJvbikgJT4lCiAgICBhZGRDaXJjbGVNYXJrZXJzKAogICAgZGF0YSA9IGNvb2xpbmdjZW50ZXJzY2xlYW4sCiAgICBjb2xvciA9ICIjRUU5MjUzIiwKICAgIG9wYWNpdHkgPSAwLjUsCiAgICByYWRpdXMgPSAxLAogICAgfmxvbmcsIH5sYXQsIHBvcHVwID0gfmh0bWxFc2NhcGUoZmFjaWxpdHkpKQpgYGAKCiMjIyBTdGVwIDg6IENyZWF0ZSBhbiBpbnRlcmFjdGl2ZSBiYXIgZ3JhcGgKU2ltaWxhciB0byBob3cgd2UgY3JlYXRlZCBhIGN1c3RvbSBpbnRlcmFjdGl2ZSBkb3QgbWFwLCB3ZSBjYW4gZG8gdGhlIHNhbWUgZm9yIGJhciBncmFwaHMuCgpgYGB7cn0KI0knbSBnb2luZyB0byBjcmVhdGUgYSB0b29sdGlwIGZpcnN0IHRvIG1ha2UgdGhlIGJhciBncmFwaCBpbnRlcmFjdGl2ZS4gCmhlYXRob3NwaXRhbGl6YXRpb25zIDwtIGhlYXRob3NwaXRhbGl6YXRpb25zICU+JSBtdXRhdGUoCiAgICB0b29sdGlwX3RleHQgPSBwYXN0ZTAoeWVhciwgIiAtICIsIHZhbHVlLCAiJSIpKQoKI05vdywgSSdtIGdvaW5nIHRvIHVzZSBnZ3Bsb3QgdG8gY3JlYXRlIHRoZSBiYXIgZ3JhcGguCmJhcl9ncmFwaF8gPC0gaGVhdGhvc3BpdGFsaXphdGlvbnMgJT4lIAogIGZpbHRlcihzdGF0ZT09Ik1pc3NvdXJpIikgJT4lIAogIGdncGxvdChhZXMoeD15ZWFyLCB5PXZhbHVlLCB0b29sdGlwID0gdG9vbHRpcF90ZXh0LCBkYXRhX2lkID0gc3RhdGUpKSArIAogIGdlb21fY29sX2ludGVyYWN0aXZlKHdpZHRoPS43LCBmaWxsPSIjRUU5MjUzIiwgc2l6ZSA9IDAuMikgKyAKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dD1lbGVtZW50X3RleHQoc2l6ZSA9IDcpLCBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTcpLCAgICAgICAgdGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9NykpICsKICAgbGFicyh0aXRsZSA9ICJQZXJjZW50YWdlIG9mIGhlYXQtcmVsYXRlZCBpbGxuZXNzIGhvc3BpdGFsaXphdGlvbnMgaW4gTWlzc291cmkgcGVyIDEwMGsgcGVvcGxlIixzdWJ0aXRsZSA9ICJEYXRhIGZyb20gQ0RDIikgKwogICB5bGFiKCJQZXJjZW50YWdlIG9mIGhlYXQgaG9zcGl0YWxpemF0aW9ucyIpICsKICAgeGxhYigiWWVhciIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAyLjAxMDEzMyxjb2xvcj0icmVkIiwgbGluZXdpZHRoPS41KQogIAojR2lyYWZlIHdpbGwgbGV0IHVzIG1ha2UgdGhlIGdyYXBoIGludGVyYWN0aXZlLgpiYXJfZ3JhcGggPC0gZ2lyYWZlKGdnb2JqID0gYmFyX2dyYXBoXywgd2lkdGhfc3ZnID0gNSwgaGVpZ2h0X3N2ZyA9IDMpCgpgYGAKCgpgYGB7cn0KaHVkX3N0YXRlcyA8LSAKICBodWRfbW8gJT4lIAogIG11dGF0ZShjb3VudHkgPSBzdHJfdG9fbG93ZXIoY291bnR5KSkgJT4lIAogIHJpZ2h0X2pvaW4obW9jb3VudGllcywgYnkgPSBjKCJjb3VudHkiID0gInN1YnJlZ2lvbiIpKQoKY2hsb3JvX21hcCA8LWdncGxvdChodWRfc3RhdGVzLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSB1bnNoZWx0ZXJlZF90b3RhbCkpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGdlb21fcG9seWdvbihjb2xvdXIgPSAiYmxhY2siLCBsaW5ld2lkdGggPSAuMSkgKwogIGNvb3JkX2ZpeGVkKDEuMykgKwogIHNjYWxlX2ZpbGxfZ3JhZGllbnQyKGxvdyA9ICIjRkVGOUU3IiwgbWlkID0gIiNGNEQwM0YiLCBoaWdoID0gIiM3RDY2MDgiKSArCiAgbGFicyh0aXRsZSA9ICJIVUQgVGl0bGUiLHN1YnRpdGxlID0gIkRhdGEgZnJvbSBDREMiKSArCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gJyNGOEY5RjknLCBjb2xvciA9ICcjRjhGOUY5JykpCmBgYAoKIyMjIFN0ZXAgOTogU29tZSBiYXNpYyBhbmFseXNpcwoKYGBge3J9CmNvb2xpbmdjZW50ZXJzY2xlYW4gJT4lIAogIGZpbHRlcih0cmFuc3BvcnRhdGlvbiA9PSAiWWVzIikKI05vIGNlbnRlcnMgcHJvdmlkZSB0cmFuc3BvcnRhdGlvbgoKY29vbGluZ2NlbnRlcnNjbGVhbiAlPiUgCiAgZmlsdGVyKGFkYV9hY2Nlc3NpYmxlID09ICJObyIpCiNBbGwgY2VudGVycyBhcmUgQURBIGFjY2Vzc2libGUKCmNvb2xpbmdjZW50ZXJzY2xlYW4gJT4lIAogIGdyb3VwX2J5KGNvdW50eSkgJT4lIAogIGNvdW50KGNvdW50eSkgJT4lIAogIGFycmFuZ2UoZGVzYyhuKSkKI0phY2tzb24gQ291bnR5IGhhcyB0aGUgbW9zdCBjb29saW5nIGNlbnRlcnMgZm9sbG93ZWQgYnkgU3QuIExvdWlzIGNvdW50eSBhbmQgdGhlbiBNYWRpc29uCgpjb29saW5nY2VudGVyc2NsZWFuICU+JSAKICBmaWx0ZXIoY291bnR5ID09ICJCb29uZSIpCiNCb29uZSBDb3VudHkgaGFzIDYgY29vbGluZyBjZW50ZXJzCgpjb29saW5nY2VudGVyc2NsZWFuICU+JSAKICBmaWx0ZXIoZ3JlcGwoInN1biIsIGhvdXJzX29mX29wZXJhdGlvbiwgaWdub3JlLmNhc2U9VCkpCiM1OCBjZW50ZXJzIGFyZSBvcGVuIG9uIFN1bmRheXMKCmhlYXRob3NwaXRhbGl6YXRpb25zICU+JSAKICBhcnJhbmdlKGRlc2ModmFsdWUpKQojQ2FsaWZvcm5pYSBoYWQgdGhlIGhpZ2hlc3QgaGVhdC1yZWxhdGVkIGhvc3BpdGFsaXphdGlvbiByYXRlIGluIDIwMjA7IE1pc3NvdXJpIGhhZCB0aGUgc2l4dGggaGlnaGVzdCByYXRlIGluIDIwMTEgYXQgNy42LgoKaGVhdGhvc3BpdGFsaXphdGlvbnMgJT4lIAogIGZpbHRlcihzdGF0ZT09Ik1pc3NvdXJpIikgJT4lIAogIGFycmFuZ2UoZGVzYyh2YWx1ZSkpCiNNaXNzb3VyaSBoYWQgaXRzIGhpZ2hlc3QgbnVtYmVyIG9mIGhlYXQtcmVsYXRlZCBob3NwaXRhbGl6YXRpb25zIGluIDIwMTEKCmhlYXRob3NwaXRhbGl6YXRpb25zICU+JSAKICBzdW1tYXJpc2UoYXZlcmFnZSA9IG1lYW4odmFsdWUpKQojVGhlIGF2ZXJhZ2UgcGVyY2VudGFnZSBvZiBoZWF0LXJlbGF0ZWQgaWxsbmVzcyBob3NwaXRhbGl6YXRpb25zIGZyb20gMjAwMCB0byAyMDIxIHVzaW5nIGF2YWlsYmxlIGRhdGEgd2FzIDIuMDEwMTMzJS4KCmhlYXRob3NwaXRhbGl6YXRpb25zICU+JSAKICBncm91cF9ieShzdGF0ZSkgJT4lIAogIHN1bW1hcmlzZShhdmVyYWdlID0gbWVhbih2YWx1ZSkpICU+JSAKICBhcnJhbmdlKGRlc2MoYXZlcmFnZSkpCiNNaXNzb3VyaSBoYXMgdGhlIHNlY29uZCBoaWdoZXN0IHJhdGUgb2YgdGhlIGRhdGEgcmVwb3J0ZWQuIAoKcHJvamVjdGVkaGVhdCAlPiUgCiAgZ3JvdXBfYnkoc3RhdGUpICU+JQogIHN1bW1hcmlzZShhdmVyYWdlPW1lYW4odmFsdWUpKSAlPiUgCiAgYXJyYW5nZShkZXNjKGF2ZXJhZ2UpKQojTWlzc291cmkgcmFua3MgdGVudGggaW4gInByb2plY3RlZCBkaWZmZXJlbmNlIGluIGV4dHJlbWUgaGVhdCBkYXlzIGFzIGNvbXBhcmVkIHRvIHRoZSBoaXN0b3JpY2FsIHBlcmlvZCIgd2l0aCBhbiBhdmVyYWdlIGFjcm9zcyB0aGUgc3RhdGUgb2YgYWJvdXQgMjQgZGF5cy4gCgpgYGAKCiMjIyBTdG9yeSBQYWNrYWdlCgoqKkltcG9ydGFudCBzdGF0aXN0aWNzIGFuZCBkYXRhIGFuYWx5c2lzIHRvIGluY2x1ZGUgaW4gdGhlIHN0b3J5OioqCgpJbiB0aGUgbGFzdCB0d28gZGVjYWRlcywgTWlzc291cmkgcmFua3MgaW4gdGhlIHRvcCB0ZW4gb3V0IG9mIHJlcG9ydGluZyBzdGF0ZXMgZm9yIHRoZSBoaWdoZXN0IHJhdGUgb2YgaGVhdC1yZWxhdGVkIGlsbG5lc3NlcyBwZXIgMTAwLDAwMCBwZW9wbGUuIEluIDIwMTEsIHRoZSByYXRlIGluIE1pc3NvdXJpIHJlYWNoZWQgNy42JSwgcmFua2luZyBpdCBudW1iZXIgNiBiZWhpbmQgQXJpem9uYS4KCk1pc3NvdXJpIGN1cnJlbnRseSByZXBvcnRzIDUzOCBjb29saW5nIGNlbnRlcnMuIDU4IG9mIHRob3NlIGNvb2xpbmcgY2VudGVycyBhcmUgb3BlbiBvbiBTdW5kYXlzLiAKCioqR3JhcGhzIHRvIGluY2x1ZGUgaW4gdGhlIHN0b3J5OioqCgpgYGB7cn0Kc3RhdGljZG90bWFwCmBgYApgYGB7cn0KaW50ZXJhY3RpdmVkb3RtYXAKYGBgCmBgYHtyfQpiYXJfZ3JhcGgKYGBgCmBgYHtyfQpjaGxvcm9fbWFwCmBgYAoKYGBge3J9CmFuaW1hdGVkZ3JhcGgKCmJhcl9ncmFwaCArIAogIHRyYW5zaXRpb25fc3RhdGVzKHllYXIsCiAgdHJhbnNpdGlvbl9sZW5ndGggPSAyLAogIHN0YXRlX2xlbmd0aCA9IDEpICsKICBlYXNlX2Flcygnc2luZS1pbi1vdXQnKQpgYGAK